import os
import tempfile
import subprocess
from modules.common.Logger import Logger


log = Logger("terminate_process.log")

def terminate_process(process, force_restart_adb=False):
    """统一的进程资源释放函数，增加了重启adb服务器的选项"""
    # 1. 尝试终止由 Popen 创建的子进程
    if process and process.poll() is None:  # 检查进程是否仍在运行
        log.info(f"尝试终止进程 PID: {process.pid}")
        try:
            process.terminate()  # 首先尝试优雅关闭
            process.wait(timeout=5)  # 等待子进程退出
            log.info(f"进程 {process.pid} 已正常退出。")
        except subprocess.TimeoutExpired:
            log.info(f"进程 {process.pid} 超时，强制杀死。")
            process.kill()  # 如果超时，强制杀死进程
        except Exception as e:
            log.error(f"释放进程 {process.pid} 资源时出错: {str(e)}")
    
    # 2. 如果指定，则强制重启 ADB 服务器
    if force_restart_adb:
        log.info("检测到ADB相关命令超时，正在强制重启ADB服务器...")
        try:
            # 创建一个新进程来执行 adb kill-server，并等待它完成
            # 使用 run 是因为它更简单，能等待命令完成
            subprocess.run(["adb", "kill-server"], timeout=10, check=True)
            log.info("ADB 服务器已成功关闭。下次adb命令会自动重启它。")
        except Exception as e:
            log.error(f"执行 'adb kill-server' 失败: {e}")

def exec_cmd(cmdline, timeout=60):
    """执行命令并返回结果"""
    if not cmdline:
        return [], "Empty command"
        
    with tempfile.SpooledTemporaryFile(10000) as out_temp:
        process = None
        try:
            process = subprocess.Popen(cmdline, stdout=out_temp, stderr=out_temp, shell=False)
            try:
                process.communicate(timeout=timeout)
                return_code = process.returncode
                if return_code != 0:
                    log.warning(f"命令返回非零退出码: {return_code}, 命令: {cmdline}")
            except subprocess.TimeoutExpired:
                log.error(f"执行命令超时：{cmdline}")
                terminate_process(process)
                return [], "TimeoutExpired"
            except Exception as e:
                log.error(f"执行命令异常：{cmdline}, 错误: {e}")
                terminate_process(process)
                return [], f"Command execution error: {e}"
        finally:
            terminate_process(process)

        out_temp.seek(0)
        try:
            lines = out_temp.readlines()
            return [line.decode('utf-8', errors='ignore') if isinstance(line, bytes) else line for line in lines], None
        except Exception as e:
            log.error(f"读取命令输出失败: {e}")
            return [], f"Output read error: {e}"


def cmd_exec_and_save(cmdline, result_file, timeout=None):
    """执行命令并将输出保存到文件"""
    log.info("cmd_exec_and_save start")
    process = None
    with open(result_file, "w") as o_file:
        try:
            process = subprocess.Popen(cmdline, stdout=o_file, stderr=o_file, shell=True)
            try:
                if timeout is None:
                    process.communicate()
                else:
                    process.communicate(timeout=timeout)
            except subprocess.TimeoutExpired:
                print(f"执行命令超时：{cmdline}")
                terminate_process(process)
                return False, "TimeoutExpired"
        finally:
            terminate_process(process)

    return True, None


def execute_cmd_infinite(cmdline, max_retries=5):
    """无限执行命令（添加最大重试限制）"""
    retries = 0
    while retries < max_retries:
        process = None
        with tempfile.SpooledTemporaryFile(10000) as out_temp:
            try:
                process = subprocess.Popen(cmdline, stdout=out_temp, stderr=out_temp, shell=True)
                process.communicate(timeout=15)
                out_temp.seek(0)
                return out_temp.readlines()
            except subprocess.TimeoutExpired:
                retries += 1
                print(f"命令超时，重试 ({retries}/{max_retries})：{cmdline}")
                terminate_process(process)
            finally:
                terminate_process(process)

    print(f"命令执行失败，达到最大重试次数：{cmdline}")
    return None


def execute_cmd_kill(cmdline, sn, package_name):
    """执行命令并在超时时强制停止 adb 进程"""
    if not cmdline:
        return []
        
    process = None
    try:
        process = subprocess.Popen(
            cmdline, 
            stdout=subprocess.PIPE, 
            stderr=subprocess.PIPE, 
            shell=False,
            bufsize=1, 
            text=True 
        )
        
        try:
            stdout, stderr = process.communicate(timeout=15)
            if stderr:
                log.warning(f"命令执行 stderr: {stderr}")
            
            # 检查返回码
            if process.returncode != 0:
                log.warning(f"命令返回非零退出码: {process.returncode}, stderr: {stderr}")

            return stdout.splitlines() if stdout else []

        except subprocess.TimeoutExpired:
            log.error(f"执行命令超时：{cmdline}")
            terminate_process(process)
            # 强制停止应用进程
            try:
                force_stop_cmd = ["adb", "-s", sn, "shell", "am", "force-stop", package_name]
                exec_cmd(force_stop_cmd, timeout=10)
            except Exception as e:
                log.error(f"强制停止应用失败: {e}")
            return []
        except Exception as e:
            log.error(f"执行命令异常：{cmdline}, 错误: {e}")
            terminate_process(process)
            return []

    except Exception as e:
        log.error(f"创建进程失败：{cmdline}, 错误: {e}")
        return []
    finally:
        terminate_process(process)


def execute_cmd(cmdline, timeout=15, shell=True):
    """执行命令并返回结果"""
    process = None
    with tempfile.SpooledTemporaryFile(10000) as out_temp:
        try:
            process = subprocess.Popen(cmdline, stdout=out_temp, stderr=out_temp, shell=shell)
            try:
                process.communicate(timeout=timeout)
            except subprocess.TimeoutExpired:
                print(f"执行命令超时：{cmdline}")
        finally:
            terminate_process(process)

        out_temp.seek(0)
        return out_temp.readlines()


def execute_cmd_rlt_read(cmdline):
    """执行命令并读取结果"""
    process = None
    with tempfile.SpooledTemporaryFile(10000) as out_temp:
        try:
            process = subprocess.Popen(cmdline, stdout=out_temp, stderr=out_temp, shell=True)
            try:
                process.communicate(timeout=15)
            except subprocess.TimeoutExpired:
                print(f"执行命令超时：{cmdline}")
        finally:
            terminate_process(process)

        out_temp.seek(0)
        return out_temp.read()


def systrace(trace, path):
    """执行 systrace 命令"""
    dumptrace = f"{trace} > {path}"
    try:
        subprocess.run(dumptrace, shell=True, check=True)
    except subprocess.CalledProcessError as e:
        print(f"执行 systrace 命令失败：{dumptrace}, 错误：{e}")
